<template>
  <div class="tags-view-container">
    <div class="tags-view-wrapper">
      <router-link
        class="tags-view-item"
        :class="{active: isActive(tag)}"
        v-for="(tag, index) in visitedTags"
        :key="index"
        :to="jumpLink(tag)"
        tag="span"
      >
        {{ tag.meta.title }}
        <span
          v-if="!isAffix(tag)"
          class="el-icon-close"
          @click.prevent.stop="closeSelectedTag(tag)"
        ></span>
      </router-link>
    </div>
  </div>
</template>

<script lang="ts">
import { defineComponent, computed, watch, onMounted } from 'vue'
import { useRoute, RouteRecordRaw, useRouter } from 'vue-router'
import { useStore } from '@/store'
import { RouteLocationWithFullPath } from '@/store/modules/tagsView'
import { routes } from '@/router'
import path from 'path'
export default defineComponent({
  name: 'TagsView',
  setup() {
    const store = useStore()
    const route = useRoute()
    const router = useRouter()
    // 可显示的tags view
    const visitedTags = computed(() => store.state.tagsView.visitedViews)
    // 添加tag
    const addTags = () => {
      const { name } = route
      if (name) {
        store.dispatch('tagsView/addView', route)
      }
    }
    // 路径发生变化追加tags view
    watch(() => route.path, () => {
      addTags()
    })

    onMounted(() => {
      initTags()
      addTags()
    })

    // 是否时当前应该激活的tag
    const isActive = (tag: RouteRecordRaw) => {
      return tag.path === route.path
    }
    // 关闭当前右键的tag路由
    const closeSelectedTag = (view: RouteLocationWithFullPath) => {
      store.dispatch('tagsView/delView', view).then(() => {
        if (isActive(view)) {
          toLastView(visitedTags.value, view)
        }
      })
    }
    // 查找最后一个tagView
    const toLastView = (visitedViews: RouteLocationWithFullPath[], view: RouteLocationWithFullPath) => {
      const lastView = visitedViews[visitedViews.length - 1]
      if (lastView) {
        router.push(lastView.fullPath as string)
      } else { // 集合中都没有tag view时
        if (view.name === 'Dashboard') {
          router.replace({ path: '/redirect' + view.fullPath as string })
        } else { // 跳回首页
          router.push('/')
        }
      }
    }
    // 跳转url
    const jumpLink = (tag: RouteLocationWithFullPath) => {
      const { path, query, fullPath } = tag
      return {
        path,
        query,
        fullPath
      }
    }

    // 初始添加affix的tag
    const initTags = () => {
      const affixTags = filterAffixTags(routes)
      for (const tag of affixTags) {
        if (tag.name) {
          console.log('tag', tag)
          store.dispatch('tagsView/addVisitedView', tag)
        }
      }
    }

    // 对于要affix的路由 我们在最开始页面加载的时候，就要筛选出来，渲染到标签导航开头，并且不显示关闭icon
    // 从路由表中过滤出要affixed tagviews
    const filterAffixTags = (routes: Array<RouteLocationWithFullPath | RouteRecordRaw>, basePath = '/') => {
      let tags: RouteLocationWithFullPath[] = []
      routes.forEach(route => {
        if (route.meta && route.meta.affix) {
          // 把路由路径解析成完整路径，路由可能是相对路径 只有/dashboard之类的路由才能固定
          const tagPath = path.resolve(basePath, route.path)
          tags.push({
            name: route.name,
            path: tagPath,
            fullPath: tagPath,
            meta: { ...route.meta }
          } as RouteLocationWithFullPath)
        }
        // 深度优先遍历 子路由（子路由路径可能相对于route.path父路由路径）
        if (route.children) {
          const childTags = filterAffixTags(route.children)
          if (childTags.length) {
            tags = [...tags, ...childTags]
          }
        }
      })
      return tags
    }

    // 是否是始终固定在tagsview上的tag
    const isAffix = (tag: RouteLocationWithFullPath) => {
      return tag.meta && tag.meta.affix
    }
    return {
      visitedTags,
      isActive,
      closeSelectedTag,
      jumpLink,
      isAffix
    }
  }
})
</script>

<style lang="scss" scoped>
.tags-view-container {
  width: 100%;
  height: 34px;
  background: #fff;
  border-bottom: 1px solid #d8dce5;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
  .tags-view-wrapper {
    text-align: left;
    .tags-view-item {
      display: inline-block;
      height: 26px;
      line-height: 26px;
      border: 1px solid #d8dce5;
      background: #fff;
      color: #495060;
      padding: 0 8px;
      box-sizing: border-box;
      font-size: 12px;
      margin-left: 5px;
      margin-top: 4px;
      &:first-of-type {
        margin-left: 15px;
      }
      &:last-of-type {
        margin-right: 15px;
      }
      &.active {
        background-color: #42b983;
        color: #fff;
        border-color: #42b983;
        &::before {
          position: relative;
          display: inline-block;
          content: '';
          width: 8px;
          height: 8px;
          border-radius: 50%;
          margin-right: 5px;
          background: #fff;
        }
      }
    }
  }
}
</style>
<style lang="scss">
.tags-view-container {
  .el-icon-close {
    width: 16px;
    height: 16px;
    position: relative;
    left: 2px;
    border-radius: 50%;
    text-align: center;
    transition: all .3s cubic-bezier(.645, .045, .355, 1);
    transform-origin: 100% 50%;
    &:before {
      transform: scale(.6);
      display: inline-block;
      vertical-align: -1px;
    }
    &:hover {
      background-color: #b4bccc;
      color: #fff;
    }
  }
}
</style>
